package com.fly.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Aspect
@Component
@Slf4j
public class TemplateAspect {

    // 定义切点（切入点表达式）
    @Pointcut("execution(* com.fly.controller.*.*(..))")
    public void controllerMethods() {
        // 切点方法无需内容，作为标识即可
    }

    // 前置通知
    @Before("controllerMethods()")
    public void beforeAdvice(JoinPoint joinPoint) {
        log.info("前置通知：{}.{}方法执行前...", joinPoint.getTarget().getClass().getName(), joinPoint.getSignature().getName());
    }

    // 后置通知
    @After("controllerMethods()")
    public void afterAdvice(JoinPoint joinPoint) {
        log.info("后置通知：{}.{}方法执行后...", joinPoint.getTarget().getClass().getName(), joinPoint.getSignature().getName());
    }

    // 返回通知
    @AfterReturning(pointcut = "controllerMethods()", returning = "result")
    public void afterReturningAdvice(JoinPoint joinPoint, Object result) {
        log.info("返回通知：{}.{}方法返回：{}", joinPoint.getTarget().getClass().getName(), joinPoint.getSignature().getName(), result);
    }

    // 异常通知
    @AfterThrowing(pointcut = "controllerMethods()", throwing = "exception")
    public void afterThrowingAdvice(Exception exception) {
        log.error("Method threw an exception: {}", exception.getMessage());
    }

    // 环绕通知
    @Around("controllerMethods()")
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取方法名
        String methodName = joinPoint.getSignature().getName();
        // 获取目标类名
        String className = joinPoint.getTarget().getClass().getName();
        //打印日志
        log.info("环绕通知：{}.{}执行方法前...", className, methodName);
        Object result = joinPoint.proceed(); // 执行目标方法
        log.info("环绕通知：{}.{}执行方法后...", className, methodName);
        return result;
    }
}